import socket
import websockets
import asyncio


# -------------------------- 1. 产品接口：统一网络连接接口 --------------------------
class NetworkConnection:
    def connect(self) -> bool:
        raise NotImplementedError("子类必须实现connect方法")

    def send_data(self, data: bytes) -> bool:
        raise NotImplementedError("子类必须实现send_data方法")

    def close(self) -> None:
        raise NotImplementedError("子类必须实现close方法")


# -------------------------- 2. 具体产品实现 --------------------------
# TCP连接
class TcpConnection(NetworkConnection):
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.socket = None

    def connect(self) -> bool:
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.host, self.port))
            print(f"[TCP] 连接成功：{self.host}:{self.port}")
            return True
        except Exception as e:
            print(f"[TCP] 连接失败：{e}")
            return False

    def send_data(self, data: bytes) -> bool:
        if not self.socket:
            print("[TCP] 连接未建立，无法发送")
            return False
        try:
            self.socket.sendall(data)
            print(f"[TCP] 发送成功：{len(data)}字节")
            return True
        except Exception as e:
            print(f"[TCP] 发送失败：{e}")
            return False

    def close(self) -> None:
        if self.socket:
            self.socket.close()
            print(f"[TCP] 连接关闭：{self.host}:{self.port}")
            self.socket = None


# UDP连接
class UdpConnection(NetworkConnection):
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.socket = None

    def connect(self) -> bool:
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            print(f"[UDP] 初始化成功（目标：{self.host}:{self.port}）")
            return True
        except Exception as e:
            print(f"[UDP] 初始化失败：{e}")
            return False

    def send_data(self, data: bytes) -> bool:
        if not self.socket:
            print("[UDP] 未初始化，无法发送")
            return False
        try:
            self.socket.sendto(data, (self.host, self.port))
            print(f"[UDP] 发送成功：{len(data)}字节")
            return True
        except Exception as e:
            print(f"[UDP] 发送失败：{e}")
            return False

    def close(self) -> None:
        if self.socket:
            self.socket.close()
            print("[UDP] 连接关闭")
            self.socket = None


# WebSocket连接
class WsConnection(NetworkConnection):
    def __init__(self, url: str):
        self.url = url
        self.websocket = None
        self.loop = None

    def connect(self) -> bool:
        try:
            self.loop = asyncio.get_event_loop()
            self.websocket = self.loop.run_until_complete(websockets.connect(self.url))
            print(f"[WebSocket] 连接成功：{self.url}")
            return True
        except Exception as e:
            print(f"[WebSocket] 连接失败：{e}")
            return False

    def send_data(self, data: bytes) -> bool:
        if not self.websocket or not self.loop:
            print("[WebSocket] 连接未建立，无法发送")
            return False
        try:
            self.loop.run_until_complete(self.websocket.send(data))
            print(f"[WebSocket] 发送成功：{len(data)}字节")
            return True
        except Exception as e:
            print(f"[WebSocket] 发送失败：{e}")
            return False

    def close(self) -> None:
        if self.websocket and self.loop:
            self.loop.run_until_complete(self.websocket.close())
            print(f"[WebSocket] 连接关闭：{self.url}")
            self.websocket = None
            self.loop = None


# -------------------------- 3. 工厂接口 --------------------------
class ConnectionFactory:
    def create_connection(self, **kwargs) -> NetworkConnection:
        """创建网络连接的工厂方法，由子类实现"""
        raise NotImplementedError("子类必须实现create_connection方法")


# -------------------------- 4. 具体工厂实现 --------------------------
class TcpFactory(ConnectionFactory):
    def create_connection(self,** kwargs) -> NetworkConnection:
        if "host" not in kwargs or "port" not in kwargs:
            raise ValueError("TCP连接需要host和port参数")
        return TcpConnection(host=kwargs["host"], port=kwargs["port"])


class UdpFactory(ConnectionFactory):
    def create_connection(self, **kwargs) -> NetworkConnection:
        if "host" not in kwargs or "port" not in kwargs:
            raise ValueError("UDP连接需要host和port参数")
        return UdpConnection(host=kwargs["host"], port=kwargs["port"])


class WsFactory(ConnectionFactory):
    def create_connection(self,** kwargs) -> NetworkConnection:
        if "url" not in kwargs:
            raise ValueError("WebSocket连接需要url参数")
        return WsConnection(url=kwargs["url"])


# -------------------------- 5. 客户端使用 --------------------------
if __name__ == "__main__":
    # 创建TCP连接（通过TCP专属工厂）
    tcp_factory = TcpFactory()
    tcp_conn = tcp_factory.create_connection(host="127.0.0.1", port=8080)
    if tcp_conn.connect():
        tcp_conn.send_data(b"TCP: Hello Server")
        tcp_conn.close()

    print("-" * 50)

    # 创建UDP连接（通过UDP专属工厂）
    udp_factory = UdpFactory()
    udp_conn = udp_factory.create_connection(host="127.0.0.1", port=8081)
    if udp_conn.connect():
        udp_conn.send_data(b"UDP: Hello Server")
        udp_conn.close()

    print("-" * 50)

    # 创建WebSocket连接（通过WebSocket专属工厂）
    ws_factory = WsFactory()
    ws_conn = ws_factory.create_connection(url="ws://127.0.0.1:8082")
    if ws_conn.connect():
        ws_conn.send_data(b"WebSocket: Hello Server")
        ws_conn.close()
